package com.carbeauty.entity;

import com.carbeauty.common.entity.BaseEntity;
import com.carbeauty.common.enums.UserRole;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * 用户实体类
 * 
 * 支持多角色用户管理:
 * - 系统管理员: 拥有所有权限
 * - 店长: 门店管理权限
 * - 员工: 基础业务权限
 * - 客户: 个人信息权限
 * 
 * @author CarBeauty Team
 */
@Entity
@Table(name = "cb_user")
public class User extends BaseEntity {
    
    /**
     * 用户名 - 登录账号，唯一
     */
    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 50, message = "用户名长度必须在3-50个字符之间")
    @Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "用户名只能包含字母、数字和下划线")
    @Column(name = "username", nullable = false, unique = true, length = 50)
    private String username;
    
    /**
     * 密码 - 加密存储
     */
    @JsonIgnore
    @NotBlank(message = "密码不能为空")
    @Column(name = "password", nullable = false, length = 100)
    private String password;
    
    /**
     * 真实姓名
     */
    @NotBlank(message = "真实姓名不能为空")
    @Size(max = 50, message = "真实姓名长度不能超过50个字符")
    @Column(name = "real_name", nullable = false, length = 50)
    private String realName;
    
    /**
     * 手机号码
     */
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号码格式不正确")
    @Column(name = "phone", length = 11)
    private String phone;
    
    /**
     * 邮箱地址
     */
    @Email(message = "邮箱格式不正确")
    @Column(name = "email", length = 100)
    private String email;
    
    /**
     * 用户角色
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "role", nullable = false, length = 20)
    private UserRole role = UserRole.CUSTOMER;
    
    /**
     * 头像URL
     */
    @Column(name = "avatar", length = 200)
    private String avatar;
    
    /**
     * 性别 (M-男, F-女, U-未知)
     */
    @Pattern(regexp = "^[MFU]$", message = "性别只能是M(男)、F(女)或U(未知)")
    @Column(name = "gender", length = 1)
    private String gender = "U";
    
    /**
     * 生日
     */
    @Column(name = "birthday")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate birthday;
    
    /**
     * 地址
     */
    @Size(max = 200, message = "地址长度不能超过200个字符")
    @Column(name = "address", length = 200)
    private String address;
    
    /**
     * 账户余额 - 仅客户角色使用
     */
    @Column(name = "balance", precision = 10, scale = 2)
    private BigDecimal balance = BigDecimal.ZERO;
    
    /**
     * 积分 - 仅客户角色使用
     */
    @Column(name = "points")
    private Integer points = 0;
    
    /**
     * 会员等级 - 仅客户角色使用
     */
    @Column(name = "member_level", length = 20)
    private String memberLevel = "普通会员";
    
    /**
     * 最后登录时间
     */
    @Column(name = "last_login_time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime lastLoginTime;
    
    /**
     * 最后登录IP
     */
    @Column(name = "last_login_ip", length = 50)
    private String lastLoginIp;
    
    /**
     * 是否首次登录
     */
    @Column(name = "is_first_login")
    private Boolean isFirstLogin = true;
    
    // ==================== 构造方法 ====================
    
    public User() {
        super();
    }
    
    public User(String username, String password, String realName, UserRole role) {
        super();
        this.username = username;
        this.password = password;
        this.realName = realName;
        this.role = role;
    }
    
    // ==================== Getter/Setter ====================
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getPassword() {
        return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    public String getRealName() {
        return realName;
    }
    
    public void setRealName(String realName) {
        this.realName = realName;
    }
    
    public String getPhone() {
        return phone;
    }
    
    public void setPhone(String phone) {
        this.phone = phone;
    }
    
    public String getEmail() {
        return email;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    
    public UserRole getRole() {
        return role;
    }
    
    public void setRole(UserRole role) {
        this.role = role;
    }
    
    public String getAvatar() {
        return avatar;
    }
    
    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }
    
    public String getGender() {
        return gender;
    }
    
    public void setGender(String gender) {
        this.gender = gender;
    }
    
    public LocalDate getBirthday() {
        return birthday;
    }
    
    public void setBirthday(LocalDate birthday) {
        this.birthday = birthday;
    }
    
    public String getAddress() {
        return address;
    }
    
    public void setAddress(String address) {
        this.address = address;
    }
    
    public BigDecimal getBalance() {
        return balance;
    }
    
    public void setBalance(BigDecimal balance) {
        this.balance = balance;
    }
    
    public Integer getPoints() {
        return points;
    }
    
    public void setPoints(Integer points) {
        this.points = points;
    }
    
    public String getMemberLevel() {
        return memberLevel;
    }
    
    public void setMemberLevel(String memberLevel) {
        this.memberLevel = memberLevel;
    }
    
    public LocalDateTime getLastLoginTime() {
        return lastLoginTime;
    }
    
    public void setLastLoginTime(LocalDateTime lastLoginTime) {
        this.lastLoginTime = lastLoginTime;
    }
    
    public String getLastLoginIp() {
        return lastLoginIp;
    }
    
    public void setLastLoginIp(String lastLoginIp) {
        this.lastLoginIp = lastLoginIp;
    }
    
    public Boolean getIsFirstLogin() {
        return isFirstLogin;
    }
    
    public void setIsFirstLogin(Boolean isFirstLogin) {
        this.isFirstLogin = isFirstLogin;
    }
    
    // ==================== 业务方法 ====================
    
    /**
     * 检查是否为客户角色
     */
    public boolean isCustomer() {
        return UserRole.CUSTOMER.equals(this.role);
    }
    
    /**
     * 检查是否为员工角色(包含管理层)
     */
    public boolean isEmployee() {
        return this.role.isEmployee();
    }
    
    /**
     * 检查是否为管理层角色
     */
    public boolean isManager() {
        return this.role.isManager();
    }
    
    /**
     * 检查是否为管理员
     */
    public boolean isAdmin() {
        return this.role.isAdmin();
    }
    
    /**
     * 增加余额
     */
    public void addBalance(BigDecimal amount) {
        if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) {
            this.balance = this.balance.add(amount);
        }
    }
    
    /**
     * 扣减余额
     */
    public boolean deductBalance(BigDecimal amount) {
        if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0 
            && this.balance.compareTo(amount) >= 0) {
            this.balance = this.balance.subtract(amount);
            return true;
        }
        return false;
    }
    
    /**
     * 增加积分
     */
    public void addPoints(Integer points) {
        if (points != null && points > 0) {
            this.points += points;
        }
    }
    
    /**
     * 扣减积分
     */
    public boolean deductPoints(Integer points) {
        if (points != null && points > 0 && this.points >= points) {
            this.points -= points;
            return true;
        }
        return false;
    }
    
    /**
     * 更新登录信息
     */
    public void updateLoginInfo(String ip) {
        this.lastLoginTime = LocalDateTime.now();
        this.lastLoginIp = ip;
        this.isFirstLogin = false;
    }

    /**
     * 检查用户是否活跃
     */
    public boolean isActive() {
        return getStatus() != null && getStatus().isActive();
    }

    /**
     * 检查是否为首次登录
     */
    public boolean isFirstLogin() {
        return Boolean.TRUE.equals(isFirstLogin);
    }
}
